package lumis.portal.channel.template;

import lumis.portal.PortalException;
import lumis.portal.UnexpectedException;
import lumis.portal.serialization.operation.ICloneableConfig;
import lumis.util.XmlUtil;

import java.io.IOException;
import java.io.OutputStream;

import org.w3c.dom.Node;

/**
 * Information of the link of a channel template resource.
 * 
 * @since 4.0.0
 * @version $Revision: 12059 $ $Date: 2010-11-03 17:59:12 -0200 (Wed, 03 Nov 2010) $
 */
public class ChannelTemplateLinkConfig implements Cloneable, ICloneableConfig<ChannelTemplateLinkConfig>
{
	public static final int TYPE_ACL = 1;
	public static final int TYPE_CHANNEL = 2;
	public static final int TYPE_LOCAL_GROUP = 3;
	public static final int TYPE_SERVICE_INSTANCE = 4;
	public static final int TYPE_PAGE = 5;
	public static final int TYPE_SERVICE_INTERFACE_INSTANCE = 6;
	public static final int TYPE_SERVICE_INSTANCE_CUSTOM_PROPERTIES = 7;
	public static final int TYPE_SERVICE_INTERFACE_INSTANCE_CUSTOM_PROPERTIES = 8;
	public static final int TYPE_SERVICE_INSTANCE_DEPENDENCY = 9;

	public static final int[] elementsTypeOrder = { TYPE_ACL, TYPE_CHANNEL, TYPE_LOCAL_GROUP, TYPE_SERVICE_INSTANCE, TYPE_PAGE, TYPE_SERVICE_INTERFACE_INSTANCE,
			TYPE_SERVICE_INSTANCE_CUSTOM_PROPERTIES, TYPE_SERVICE_INTERFACE_INSTANCE_CUSTOM_PROPERTIES, TYPE_SERVICE_INSTANCE_DEPENDENCY };

	public static final Object[][] aclDependencies = { { "parentId", Integer.valueOf(TYPE_ACL) } };
	public static final Object[][] channelDependencies = { { "aclId", Integer.valueOf(TYPE_ACL) }, { "parentId", Integer.valueOf(TYPE_CHANNEL) },
			{ "parentTemplateId", Integer.valueOf(TYPE_CHANNEL) }, { "pageTemplateId", Integer.valueOf(TYPE_PAGE) } };
	public static final Object[][] localGroupDependencies = { { "aclId", Integer.valueOf(TYPE_ACL) }, { "channelId", Integer.valueOf(TYPE_CHANNEL) } };
	public static final Object[][] serviceInstanceDependencies = { { "aclId", Integer.valueOf(TYPE_ACL) }, { "channelId", Integer.valueOf(TYPE_CHANNEL) } };
	public static final Object[][] pageDependencies = { { "aclId", Integer.valueOf(TYPE_ACL) }, { "channelId", Integer.valueOf(TYPE_CHANNEL) }, { "parentTemplateId", Integer.valueOf(TYPE_PAGE) } };
	public static final Object[][] serviceInterfaceDependencies = { { "serviceInstanceId", Integer.valueOf(TYPE_SERVICE_INSTANCE) }, { "pageId", Integer.valueOf(TYPE_PAGE) },
			{ "parentInterfaceInstanceId", Integer.valueOf(TYPE_SERVICE_INTERFACE_INSTANCE) } };
	public static final Object[][] serviceInstanceCustomPropertiesDependencies = { { "serviceInstanceId", Integer.valueOf(TYPE_SERVICE_INSTANCE) }, { "pageId", Integer.valueOf(TYPE_PAGE) } };
	public static final Object[][] serviceInterfaceInstanceCustomPropertiesDependencies = { { "serviceInterfaceInstanceId", Integer.valueOf(TYPE_SERVICE_INTERFACE_INSTANCE) },
			{ "pageId", Integer.valueOf(TYPE_PAGE) } };
	public static final Object[][] serviceInstanceDependencyDependencies = { { "serviceInstanceId", Integer.valueOf(TYPE_SERVICE_INSTANCE) },
			{ "dependentServiceInstanceId", Integer.valueOf(TYPE_SERVICE_INSTANCE) } };

	// Position 0 must be empty since there is no itemType = 0
	public static final Object[][][] elementsDependenciesReplacement = { {}, aclDependencies, channelDependencies, localGroupDependencies, serviceInstanceDependencies, pageDependencies,
			serviceInterfaceDependencies, serviceInstanceCustomPropertiesDependencies, serviceInterfaceInstanceCustomPropertiesDependencies, serviceInstanceDependencyDependencies };

	private String id = null;
	private String templateChannelId = null;
	private String destinationChannelId = null;
	private String sourceId = null;
	private String destinationId = null;
	private int itemType = 0;
	private boolean linked = true;

	public String getDestinationChannelId()
	{
		return destinationChannelId;
	}

	public void setDestinationChannelId(String destinationChannelId)
	{
		this.destinationChannelId = destinationChannelId;
	}

	public String getDestinationId()
	{
		return destinationId;
	}

	public void setDestinationId(String destinationId)
	{
		this.destinationId = destinationId;
	}

	public String getId()
	{
		return id;
	}

	public void setId(String id)
	{
		this.id = id;
	}

	public int getItemType()
	{
		return itemType;
	}

	public void setItemType(int itemType)
	{
		this.itemType = itemType;
	}

	public boolean isLinked()
	{
		return linked;
	}

	public void setLinked(boolean linked)
	{
		this.linked = linked;
	}

	public String getSourceId()
	{
		return sourceId;
	}

	public void setSourceId(String sourceId)
	{
		this.sourceId = sourceId;
	}

	public String getTemplateChannelId()
	{
		return templateChannelId;
	}

	public void setTemplateChannelId(String templateChannelId)
	{
		this.templateChannelId = templateChannelId;
	}
	
	public void serialize(OutputStream outputStream) throws PortalException
	{
		try
		{
			StringBuilder stream = new StringBuilder(600);
			
			stream.append("<channelTemplateLink id=\"" + getId() + "\">");
			stream.append("<templateChannelId>" + XmlUtil.encodeXml(getTemplateChannelId()) + "</templateChannelId>");
			stream.append("<destinationChannelId>" + XmlUtil.encodeXml(getDestinationChannelId()) + "</destinationChannelId>");
			stream.append("<sourceId>" + XmlUtil.encodeXml(getSourceId()) + "</sourceId>");
			stream.append("<destinationId>" + XmlUtil.encodeXml(getDestinationId()) + "</destinationId>");
			stream.append("<itemType>" + getItemType() + "</itemType>");
			stream.append("<linked>" + isLinked() + "</linked>");
			stream.append("</channelTemplateLink>");
			
			outputStream.write(stream.toString().getBytes("UTF-8"));
		}
		catch (IOException e)
		{
			throw new UnexpectedException(e);
		}
	}
	
	public void deserialize(Node channelNode) throws PortalException
	{
		try
		{
			setId(XmlUtil.readAttributeString("id", channelNode));
			setTemplateChannelId(XmlUtil.readNodeString("templateChannelId", channelNode));
			setDestinationChannelId(XmlUtil.readNodeString("destinationChannelId", channelNode));
			setSourceId(XmlUtil.readNodeString("sourceId", channelNode));
			setDestinationId(XmlUtil.readNodeString("destinationId", channelNode));
			setItemType(XmlUtil.readNodeInt("itemType", channelNode, -1));
			setLinked(XmlUtil.readNodeBoolean("linked", channelNode, false));
		}
		catch (PortalException e)
		{
			throw e;
		}
		catch (Exception e)
		{
			throw new UnexpectedException(e);
		}
	}
	
	public ChannelTemplateLinkConfig clone() throws CloneNotSupportedException
	{
		return (ChannelTemplateLinkConfig) super.clone();
	}

	/**
	 * Returns true if all properties of this object are equals to the properties of the given object.
	 * @param channelTemplateLinkConfig the object to compare the properties with.
	 * @return true if the properties are equal, false otherwise.
	 * @since 5.6.0
	 */
	public boolean isIdentical(ChannelTemplateLinkConfig channelTemplateLinkConfig)
	{
		return 
			this.linked == channelTemplateLinkConfig.linked 
			&& this.itemType == channelTemplateLinkConfig.itemType
			&& this.destinationChannelId.equals(channelTemplateLinkConfig.destinationChannelId) 
			&& this.destinationId.equals(channelTemplateLinkConfig.destinationId)
			&& this.sourceId.equals(channelTemplateLinkConfig.sourceId)
			&& this.templateChannelId.equals(channelTemplateLinkConfig.templateChannelId);
	}
}